#ifndef OPTIONS_H
#define OPTIONS_H

#include "OptionsAPI.h"

#define OPTION_BUFFER_LENGTH 4

char loggedUser[USERNAME_LENGTH] = {0};
int loggedServerID = 0;
int loggedType = 0;

void loginScreenPrompt(){ fprintf(stdout, "Please enter a username and password.\n"); }
void loginServerPrompt(){ fprintf(stdout, "Enter server address to login to.\n"); }
int correctUserPass(char *typedPass){ char *userPass=getUserPass(loggedUser); return (userPass && !strcmp(userPass, typedPass))?1:0; }

void logout(){
	loggedType = 0;
	loggedServerID = 0;
	loggedUser[0] = '\0';
}
int loginUserCredentials(){ 
	char typedPass[PASS_LENGTH] = {0};
	char *userPass = NULL;
	int errorCount = 0;

	while( errorCount++ < 3 ){
		loginScreenPrompt();

		fgets(loggedUser, sizeof loggedUser, stdin);
		FLUSH_STDIN(loggedUser);
		fgets(typedPass, sizeof typedPass, stdin);
		FLUSH_STDIN(typedPass);

		if( correctUserPass(typedPass) )
			return 1;
		else
			printError("Incorrect username or password.\n");
	}

	printError("Too many incorrect login attempts.\n");
	return 0;
}
int loginServerAddr(){
	char serverAddr[SERVER_ADDR_LENGTH] = {0};
	int serverID = 0, errorCount = 0;

	while( errorCount++ < 3)
	{
		loginServerPrompt();
		fgets(serverAddr, sizeof serverAddr, stdin);
		FLUSH_STDIN(serverAddr);

		if( serverID = getServerID(serverAddr) )
			return serverID;
		else
			printError("No such server.\n");
	}

	printError("Too many incorrect login attempts.\n");
	return 0;
}
int setLoggedServerID(){
	int *serverID=getUserServerID(loggedUser);
	
	if( loggedType == 3 )
		return -1;
	else if( serverID && !serverID[1] )
		return *serverID;
	else
		return loginServerAddr();
}
void emergencyLoginInfo(){
	printGreen("\n\nEmergency Login Info\n\n");
	printGreen("List of private users:\n");
	privateUsersPrintAll();
	printGreen("List of servers:\n");
	serversPrintAll();
	printGreen("\n");
}
int loginScreen(){
	int loginErrorCount = 0;
	
	while( loginErrorCount++ < 3)
	{
		if( loginUserCredentials() )
		{
			loggedType = getUserType(loggedUser);
			loggedServerID = setLoggedServerID();
			if( loggedServerID ) 
				return 1;
		}
		else
			( loginErrorCount!= 3)?emergencyLoginInfo() : (loginErrorCount = 3);
	}

	return 0;
}

void optionPrompt(){ fprintf(stdout, "Please enter an option\n"); }
void noSuchOption(){ printRed("No such option.\n"); }
void noSuchServer(){ printRed("No such server.\n"); }
void noSuchService(){ printRed("No such service.\n"); }
int getOption(){ 
	char inputBuffer[OPTION_BUFFER_LENGTH] = {0};

	optionPrompt();
	fgets(inputBuffer, OPTION_BUFFER_LENGTH, stdin);
	FLUSH_STDIN(inputBuffer);

	return atoi(inputBuffer);
}
void oneServerOrAllPrompt(){printGreen("Enter server address or \"all\" for all.\n"); }
void oneServerPrompt(){printGreen("Enter server address.\n"); }
void oneServiceOrAllPrompt(){printGreen("Enter service name or \"all\" for all.\n"); }
void oneServicePrompt(){printGreen("Enter service name.\n");}
int getOptionServerAddr(char *serverAddr){
	fgets(serverAddr, SERVER_ADDR_LENGTH, stdin);
	FLUSH_STDIN(serverAddr);
	
	return 1;
}
int getOptionServiceName(char *serviceName){
	fgets(serviceName, SERVICE_NAME_LENGTH, stdin);
	FLUSH_STDIN(serviceName);
	
	return 1;

}

//////////////////////////
// Queries
/////////////////////
void printInstalledServices(int serverID){
	InstalledServicesNode *curr = installedServicesDBGetHead();
	int currServerID = 0, currServiceVerInt = 0;
	char currServiceVerChar[SERVICE_VERSION_LENGTH] = {0};

	while( curr ){
		currServerID = installedServicesNodeGetServerID(curr);
		currServiceVerInt = installedServicesNodeGetServiceVersion(curr);
		if( currServerID == serverID )
			printTableBody(3, getServerAddr(serverID), installedServicesNodeGetServiceName(curr), itoa(currServiceVerInt ,currServiceVerChar, 10));
		curr = installedServicesNodeGetNext(curr);
	}
}
void printInstalledServices_All(){
	ServerNode *curr = serversDBGetHead();
	int currServerID = 0;

	while( curr ){
		currServerID = serverNodeGetID(curr);
		printInstalledServices(currServerID);
		curr = serverNodeGetNext(curr);
	}
}
int installedServices(){
	char serverAddr[SERVER_ADDR_LENGTH] = {0};

	if( loggedType == 3 )
	{
		oneServerOrAllPrompt();
		getOptionServerAddr(serverAddr);
	}
	
	printTableHead(3, "Server IP", "Service Name", "Service Version");

	if( loggedType <= 2 )
		printInstalledServices( loggedServerID );
	else
	{
		if( !strcmp(serverAddr, "all") )
			printInstalledServices_All();
		else
			printInstalledServices( getServerID(serverAddr) );
	}

	printTableBottom();

	return 1;
}

void printOutdatedServices( int serverID ){
	InstalledServicesNode *curr = installedServicesDBGetHead();
	UpToDateVersionsNode *upToDateNode = upToDateVersionsDBGetHead();
	int currServerID = 0, currServiceID = 0, currServiceVerInt = 0;
	int serviceLatestID = 0, serviceLatestVerInt = 0;
	char currServiceVerChar[SERVICE_VERSION_LENGTH] = {0};

	while( curr ){
		currServerID = installedServicesNodeGetServerID(curr);
		currServiceVerInt = installedServicesNodeGetServiceVersion(curr);
		currServiceID = installedServicesNodeGetServiceID( curr );
		upToDateNode = upToDateVersionsDBGetHead();
		serviceLatestVerInt = 0;

		while( upToDateNode )//Find latest current service version
		{
			serviceLatestID = upToDateVersionsNodeGetServiceID( upToDateNode );
			if( currServiceID == serviceLatestID )
				serviceLatestVerInt = upToDateVersionsNodeGetServiceVersion( upToDateNode );
			upToDateNode = upToDateVersionsNodeGetNext( upToDateNode );
		}

		if( currServerID == serverID && serviceLatestVerInt > currServiceVerInt )
			printTableBody(3, getServerAddr(serverID), installedServicesNodeGetServiceName(curr), itoa(currServiceVerInt ,currServiceVerChar, 10));
		curr = installedServicesNodeGetNext(curr);
	}
}
void printOutdatedServices_All(){
	ServerNode *curr = serversDBGetHead();
	int currServerID = 0;

	while( curr ){
		currServerID = serverNodeGetID(curr);
		printOutdatedServices(currServerID);
		curr = serverNodeGetNext(curr);
	}
}
int outdatedServices(){
	char serverAddr[SERVER_ADDR_LENGTH] = {0};

	if( loggedType == 3)
	{
		oneServerOrAllPrompt();
		getOptionServerAddr(serverAddr);
	}

	printTableHead(3, "Server IP", "Service Name", "Service Version");

	if( loggedType <= 2 )
		printOutdatedServices( loggedServerID );
	else
	{
		if( !strcmp(serverAddr, "all") )
			printOutdatedServices_All();
		else
			printOutdatedServices( getServerID(serverAddr) );
	}

	printTableBottom();

	return 1;
}

void printSupportedServices_All(){
	SupportedServicesNode *currService = supportedServicesDBGetHead();
	char currServiceVerChar[SERVICE_VERSION_LENGTH] = {0};
	int currServiceID = 0, serviceUpToDateVer = 0;

	while( currService )
	{
		currServiceID = supportedServicesNodeGetServiceID( currService );		
		serviceUpToDateVer = getServiceUpToDateVer( currServiceID );
		printTableBody(2, supportedServicesNodeGetServiceName(currService), itoa(serviceUpToDateVer, currServiceVerChar, 10));
		currService = supportedServicesNodeGetNext(currService);
	}
}
int supportedServices(){

	printTableHead(2, "Service Name", "Latest Version");
	printSupportedServices_All();
	printTableBottom();

	return 1;
}

void printAllServers(){
	ServerNode *curr = serversDBGetHead();
	char serverIDchar[10] = {0};

	while(curr)
	{
		printTableBody(2, serverNodeGetAdr(curr), itoa(serverNodeGetID(curr), serverIDchar, 10));
		curr = serverNodeGetNext(curr);
	}
}
int allServers(){
	
	printTableHead(2, "Server IP", "Server ID");
	printAllServers();
	printTableBottom();
	
	return 1;
}

void printDailyOperations(int serverID){
	DailyOperationsNode *currNode = dailyOperationsDBGetHead();
	char *currUsername = NULL, *currOperation = NULL;
	char *currServerAddr = NULL;//[SERVER_ADDR_LENGTH] = {0};
	int currServerID = 0;

	while(currNode)
	{
		currServerID = dailyOperationsNodeGetServerID(currNode);
		if( currServerID == serverID )
		{
			currUsername = dailyOperationsNodeGetUserName(currNode);
			currOperation = dailyOperationsNodeGetOperation(currNode);
			currServerAddr = getServerAddr(currServerID);
			printTableBody(3, currServerAddr, currOperation, currUsername);
		}
		currNode = dailyOperationsNodeGetNext(currNode);
	}
}
int dailyOperations(){
	char serverAddr[SERVER_ADDR_LENGTH] = {0};
	char serviceName[SERVICE_NAME_LENGTH] = {0};
	int serviceID = 0, serverID = 0, upToDateVer = 0;
	int errorCount = 0;

	if( loggedType == 3 )
	{
		errorCount = 0;
		do
		{
			oneServerPrompt();
			getOptionServerAddr(serverAddr);
			serverID = getServerID(serverAddr);
			if( !serverID )
				noSuchServer();
			
		}while( !serverID && errorCount++ < 3 );
	}
	if( !serverID && errorCount == 3 )
		return 0;

	serverID = (serverID)?serverID : loggedServerID;
	printTableHead(3, "Server IP", "Operation", "Username");
	printDailyOperations(serverID);
	printTableBottom();
}

////////////////////////////
///////////////////////////////

/////////////////////////////
// Server operations
////
void deleteMessages(int serverID){
	messagesDBRemoveAllMessages(serverID);
}
void printMessages(int serverID){
	MessagesNode *currMsg = messagesDBGetHead();

	printTableHead(2, "Server IP", "Message Inbox");
	while( currMsg )
	{
		if( messagesNodeGetID(currMsg) == serverID )
			printTableBody(2, getServerAddr(serverID), messagesNodeGetMSG(currMsg));
		currMsg = messagesNodeGetNext( currMsg );
	}
	printTableBottom();
}
void inputMessageToDB(int serverID){
	char inputMessage[MESSAGE_LENGTH];

	printGreen("Please enter a message for the server Admin.\n");
	fgets(inputMessage, MESSAGE_LENGTH, stdin);
	FLUSH_STDIN(inputMessage);

	messagesDBPush(inputMessage, serverID);
}
int sendMessage(){
	char serverAddr[SERVER_ADDR_LENGTH] = {0};
	int serverID = 0;

	if( loggedType == 3 )
	{
		oneServerPrompt();
		getOptionServerAddr(serverAddr);
	}
	
	if( loggedType <= 2 )
		serverID = loggedServerID;
	else
		serverID = getServerID(serverAddr);

	
	inputMessageToDB( serverID );
	dailyOperationsDBPush(loggedUser,serverID ,"Sent message");
	printGreen("Message sent successfuly.\n");
	return 1;
}
///////////////// !!!!!!!!!!Remove message after viewing

void updateService_One(int serviceID, int serverID){
	InstalledServicesNode *curr = installedServicesDBGetHead();
	int currServerID = 0, currServiceID = 0, currServiceVerInt = 0;
	int serviceLatestID = 0, serviceLatestVerInt = 0;
	char currServiceVerChar[SERVICE_VERSION_LENGTH] = {0};

	while( curr ){
		currServerID = installedServicesNodeGetServerID(curr);
		currServiceVerInt = installedServicesNodeGetServiceVersion(curr);
		currServiceID = installedServicesNodeGetServiceID( curr );

		if( currServerID == serverID && currServiceID == serviceID)
		{
			serviceLatestVerInt = getUpToDateServiceVer(serviceID);
			if( serviceLatestVerInt > currServiceVerInt )
				installedServicesNodeSetServiceVersion(curr, serviceLatestVerInt);
		}
		curr = installedServicesNodeGetNext(curr);
	}
}
void updateService_All_OneServer(int serverID){
	InstalledServicesNode *curr = installedServicesDBGetHead();

	while( curr )
	{
		if( installedServicesNodeGetServerID(curr) == serverID )
			updateService_One( installedServicesNodeGetServiceID(curr) , serverID);
		curr = installedServicesNodeGetNext(curr);
	}
}
void updateService_OneServer(int serverID){
	char serviceName[SERVICE_NAME_LENGTH] = {0};

	oneServiceOrAllPrompt();
	getOptionServiceName(serviceName);
	if( !strcmp(serviceName, "all") )
		updateService_All_OneServer(serverID);
	else
		updateService_One(getServiceID(serviceName), serverID);
	dailyOperationsDBPush(loggedUser,serverID ,"Updated Services");
}
void updateService_All_AllServers(){
	ServerNode *curr = serversDBGetHead();
	int serverID = 0;

	while( curr )
	{
		serverID = serverNodeGetID(curr);
		updateService_All_OneServer(serverNodeGetID(curr));
		dailyOperationsDBPush(loggedUser,serverID ,"Updated Services");
		curr = serverNodeGetNext(curr);
	}

}
int updateService(){
	char serverAddr[SERVER_ADDR_LENGTH] = {0};

	if( loggedType == 3 )
	{
		oneServerOrAllPrompt();
		getOptionServerAddr(serverAddr);
		if( !strcmp(serverAddr, "all") )
			updateService_All_AllServers();
		else
			updateService_OneServer(getServerID(serverAddr));
	}
	else
		updateService_OneServer(loggedServerID);

	printGreen("Update operation completed successfuly.\n");
	return 1;
}

int installService(){
	char serverAddr[SERVER_ADDR_LENGTH] = {0};
	char serviceName[SERVICE_NAME_LENGTH] = {0};
	int serviceID = 0, serverID = 0, upToDateVer = 0;
	int errorCount = 0;

	if( loggedType == 3 )
	{
		errorCount = 0;
		do
		{
			oneServerPrompt();
			getOptionServerAddr(serverAddr);
			serverID = getServerID(serverAddr);
			if( !serverID )
				noSuchServer();
			
		}while( !serverID && errorCount++ < 3 );
	}
	if( !serverID && errorCount == 3 )
		return 0;

	errorCount = 0;
	do
	{
		oneServicePrompt();
		getOptionServiceName(serviceName);
		serviceID = getServiceID(serviceName);
		if( !serviceID )
			noSuchService();
		
	}while( !serviceID && errorCount++ < 3 );
	if( !serviceID && errorCount == 3 )
		return 0;

	serverID = (serverID)? serverID : loggedServerID;
	if( installedServiceExists(serverID, serviceID ) )
	{
		printRed("Service already installed.\n");
		return 0;
	}
	upToDateVer = getUpToDateServiceVer(serviceID);

	installedServicesDBPush(serviceName, serviceID, upToDateVer, serverID);
	dailyOperationsDBPush(loggedUser,serverID ,"Installed a service");
	printGreen("Service installed successfuly.\n");
	return 1;
}
int uninstallService(){
	char serverAddr[SERVER_ADDR_LENGTH] = {0};
	char serviceName[SERVICE_NAME_LENGTH] = {0};
	int serviceID = 0, serverID = 0;
	int errorCount = 0;

	if( loggedType == 3 )
	{
		errorCount = 0;
		do
		{
			oneServerPrompt();
			getOptionServerAddr(serverAddr);
			serverID = getServerID(serverAddr);
			if( !serverID )
				noSuchServer();
			
		}while( !serverID && errorCount++ < 3 );
	}
	if( !serverID && errorCount == 3 )
		return 0;

	errorCount = 0;
	do
	{
		oneServicePrompt();
		getOptionServiceName(serviceName);
		serviceID = getServiceID(serviceName);
		if( !serviceID )
			noSuchService();
		
	}while( !serviceID && errorCount++ < 3 );
	if( !serviceID && errorCount == 3 )
		return 0;

	serverID = (serverID)? serverID : loggedServerID;
	if( installedServicesDBRemove(serviceID, serverID ) )
	{
		dailyOperationsDBPush(loggedUser,serverID ,"Uninstalled a service");
		printGreen("Service uninstalled successfuly.\n");
		return 1;
	}

	printRed("Service not found on server.\n");
	return 0;
}

int addSuperUser(){
	char userName[USERNAME_LENGTH] = {0};
	char typedPass[PASS_LENGTH] = {0};
	int errorCount = 0;

	while( errorCount++ < 3)
	{
		loginScreenPrompt();
		fgets(userName, sizeof userName, stdin);
		FLUSH_STDIN(userName);

		if( getUserPass(userName) )
			printRed("User already exists.\n");
		else
		{
			fgets(typedPass, sizeof typedPass, stdin);
			FLUSH_STDIN(typedPass);
			superUsersDBPush(userName, typedPass);
			return 1;
		}
	}
	
	return 0;
}
int addUserAdmin(int serverID){
	char userName[USERNAME_LENGTH] = {0};
	char typedPass[PASS_LENGTH] = {0};
	int userType = 0, serverIDArr[2] = {0};
	int errorCount = 0, errorUserCount = 0;

	serverIDArr[0] = serverID;

	errorCount = 0;
	while( errorCount++ <3 )
	{
		fprintf(stdout, "1) User\n2) Admin\n");
		userType = getOption();
		
		if(userType != 1 && userType != 2)
			noSuchOption();
		else
			break;
	}
	if(userType != 1 && userType != 2)
		return 0;
		
	errorCount = 0;
	while( errorCount++ < 3 )
	{
		loginScreenPrompt();
		fgets(userName, sizeof userName, stdin);
		FLUSH_STDIN(userName);
		if( getUserPass(userName) )
			printRed("User already exists.\n");
		else
			break;
	}
	if( errorCount == 3 && getUserPass(userName) )
		return 0;

	fgets(typedPass, sizeof typedPass, stdin);
	FLUSH_STDIN(typedPass);
	
	dailyOperationsDBPush(loggedUser,serverIDArr[0] ,"Added a user");
	privateUsersDBPush(userName, typedPass, serverIDArr, userType);

	return 1;
}
int addUserAdminAsSuperUser(){
	char serverAddr[SERVER_ADDR_LENGTH] = {0};
	int errorCount = 0, serverID = 0;

	do
	{
	oneServerPrompt();
	getOptionServerAddr(serverAddr);
	serverID = getServerID(serverAddr);
	if( !serverID )
		noSuchServer();
			
	}while( !serverID && errorCount++ < 3 );
	if( !serverID && errorCount == 3 )
		return 0;

	return addUserAdmin(serverID);
}
int createUser(){
	int success = 0, option = 0, errorCount = 0;

	switch(loggedType)
	{
	case 2:
		success = addUserAdmin(loggedServerID);
		break;
	case 3:
		while( errorCount++ < 3 )
		{
			fprintf(stdout,"1) Superuser\n2)Admin/User\n\n");
			option = getOption();
			if( option!= 1 && option!= 2 )
				noSuchOption();
			else
				break;
		}
		if( option==1 || option==2 )
			success = (option==1)?addSuperUser():addUserAdminAsSuperUser();
		else
			success = 0;
		break;
	default:
		printError("Error logged in type.\n");
		break;
	}
	
	if( success )
		printGreen("User added successfuly.\n");
	else
		printRed("Failed to add user.\n");

	return 0;
}
///////////////////////////////
//////////////////////////////

//////////////////////////////
// Farm operations
/////
int addServer(){
	char serv[SERVER_ADDR_LENGTH];
	oneServerPrompt();
	getOptionServerAddr(serv);

	if ( !seversDBExists(serv) )
		serversDBPush(serv, serversDBGetSize()+1);
	else{
		printRed("This Server already exists...\n");
		return 0;
	}

	printGreen("Server added successfuly.\n");
	return 1;
}

int increaseServiceVersion(int serviceID){
	UpToDateVersionsNode *find = NULL ;

	if (find = findUpToDateVersionsNode(serviceID) )
		upToDateVersionsNodeSetServiceVersion(find, upToDateVersionsNodeGetServiceVersion(find)+100);
	else
		return 0;
	
	return 1;
}
int changeUpdateServer(){
	char svc[SERVICE_NAME_LENGTH];
	char svr[SERVER_ADDR_LENGTH];
	int ID = 0;
	UpdateServerNode *find = NULL;

	oneServerPrompt();
	getOptionServerAddr(svr);

	oneServicePrompt();
	getOptionServiceName(svc);


	if ( ID = getServiceID(svc)){

		if( updateServers_DB)
			find = updateServersDBGetHead();

		while(find){

			if( updateServerNodeGetID(find) == ID ){
				updateServerNodeSetAdr(find, svr);
				printGreen("Update Server changed successfuly.\n");
				increaseServiceVersion(ID);
				return 1;
			}//if

			find = updateServerNodeGetNext(find);
		}//while

		printGreen("Update server added successfuly.\n");
		updateServersDBPush(svr, ID);
		increaseServiceVersion(ID);

	}//if
	else{
		printRed("Service not supported\n");
		return 0;
	}//else
	return 1;

}

int addSupportedService(){
	char svc[SERVICE_NAME_LENGTH];
	int ID = 0;

	oneServicePrompt();
	getOptionServiceName(svc);

	if ( ID = getServiceID(svc)){
		printRed("Service already Exists\n");
		return 0;
	}//if
	else{
		supportedServicesDBPush(svc, SupportedServicesDBGetSize()+1);
		upToDateVersionsDBPush(SupportedServicesDBGetSize(), 0);
	}//else

	printGreen("Supported service added successfuly.\n");
	return 1;
}

////////////////////////////
///////////////////////////

int userMainMenu(){
	int option;
	
	while( loggedType == 1){
		fprintf(stdout, "\n\n\n1) Query menu\n");
		fprintf(stdout, "2) Server menu\n");
		fprintf(stdout, "3) Logout\n");
		fprintf(stdout, "4) Exit\n\n");
	
		option = getOption();
		switch( option ){
		case 1:
			userOptionsQuery();
			break;
		case 2:
			userOptionsServer();
			break;
		case 3:
			logout();
			return 1;
		case 4:
			exit(1);
		default:
			noSuchOption();
			break;
		}
	}
}
int userOptionsServer(){
	int option;

	while( 1 ){
		fprintf(stdout, "\n\n\n1) Send a message \n");
		fprintf(stdout, "2) Main Menu \n");
		fprintf(stdout, "3) Logout \n");
		fprintf(stdout, "4) Exit\n\n");
	 
		option = getOption();
		switch( option ){
		case 1:
			sendMessage();
			break;
		case 2://Main menu
			return 1;
		case 3://Logout and main menu
			logout();
			return 1;
		case 4:
			exit(1);
		default:
			noSuchOption();
			break;
		}
	}
}
int userOptionsQuery(){
	int option;

	while( 1 ){
		fprintf(stdout, "\n\n\n1) Installed services \n");
		fprintf(stdout, "2) Outdated services\n");
		fprintf(stdout, "3) Daily operations\n");
		fprintf(stdout, "4) Supported services \n");
		fprintf(stdout, "5) Main menu \n");
		fprintf(stdout, "6) Logout \n");
		fprintf(stdout, "7) Exit\n\n" );
 
		option = getOption();
		switch( option ){
		case 1: 
			installedServices();
			break;
		case 2:
			outdatedServices();
			break;
		case 3:
			dailyOperations();
			break;
		case 4:
			supportedServices();
			break;
		case 5://Go back to main menu
			return 1;
		case 6://Logout and back to main menu
			logout();
			return 1;
		case 7:
			exit(1);
		default:
			noSuchOption();
			break;
		}
	}
}

int adminMainMenu(){
	int option;
	
	while( loggedType == 2 ){
		
		fprintf(stdout, "\n\n\n1) Query menu\n");
		fprintf(stdout, "2) Server menu\n");
		fprintf(stdout, "3) Logout\n");
		fprintf(stdout, "4) Exit\n\n");
	
		option = getOption();
		switch( option ){
		case 1:
			adminOptionsQuery();
			break;
		case 2:
			adminOptionsServer();
			break;
		case 3:
			logout();
			return 1;
		case 4:
			exit(1);
		default:
			noSuchOption();
			break;
		}
	}
}
int adminOptionsServer(){
	int option;

	while( 1 ){

		
		fprintf(stdout, "\n\n\n1) Send a message\n");
		fprintf(stdout, "2) Update a service\n");
		fprintf(stdout, "3) Install a service \n");
		fprintf(stdout, "4) Uninstall a service \n");
		fprintf(stdout, "5) Create a user \n");
		fprintf(stdout, "6) Main menu \n");
		fprintf(stdout, "7) Logout \n");
		fprintf(stdout, "8) Exit\n\n" );		
		
		option = getOption();
		switch( option ){
		case 1:
			sendMessage();
			break;
		case 2:
			updateService();
			break;
		case 3:
			installService();
			break;
		case 4:
			uninstallService();
			break;
		case 5:
			createUser();
			break;
		case 6://main menu
			return 1;
		case 7://logout and main menu
			logout();
			return 1;
		case 8:
			exit(1);
		default:
			noSuchOption();
			break;
		}
	}
}
int adminOptionsQuery(){
	int option;

	while( 1 ){

		fprintf(stdout, "\n\n\n1) Installed services \n");
		fprintf(stdout, "2) Outdated services\n");
		fprintf(stdout, "3) Daily operations\n");
		fprintf(stdout, "4) Supported services \n");
		fprintf(stdout, "5) Main menu \n");
		fprintf(stdout, "6) Logout \n");
		fprintf(stdout, "7) Exit\n\n" );
		option = getOption();
		switch( option ){
		case 1: 
			installedServices();
			break;
		case 2:
			outdatedServices();
			break;
		case 3:
			dailyOperations();
			break;
		case 4:
			supportedServices();
			break;
		case 5://main menu
			return 1;
		case 6://logout and main menu
			logout();
			return 1;
		case 7:
			exit(1);
		default:
			noSuchOption();
			break;
		}
	}
}

int superUserMainMenu(){
	int option;
	
	while( loggedType == 3 ){

		fprintf(stdout, "\n\n\n1) Query menu\n");
		fprintf(stdout, "2) Server menu\n");
		fprintf(stdout, "3) Farm menu \n");
		fprintf(stdout, "4) Logout\n");
		fprintf(stdout, "5) Exit\n\n");
		option = getOption();
		switch( option ){
		case 1:
			superUserOptionsQuery();
			break;
		case 2:
			superUserOptionsServer();
			break;
		case 3:
			superUserOptionsFarm();
			break;
		case 4:
			logout();
			return 1;
		case 5:
			exit(1);
		default:
			noSuchOption();
			break;
		}
	}
}
int superUserOptionsQuery(){
	int option;

	while( 1 ){

		fprintf(stdout, "\n\n\n1) Installed services \n");
		fprintf(stdout, "2) Outdated services\n");
		fprintf(stdout, "3) Daily operations\n");
		fprintf(stdout, "4) Supported services \n");
		fprintf(stdout, "5) All servers \n");
		fprintf(stdout, "6) Main menu \n");
		fprintf(stdout, "7) Logout \n");
		fprintf(stdout, "8) Exit\n\n" );

		option = getOption();
		switch( option ){
		case 1: 
			installedServices();
			break;
		case 2:
			outdatedServices();
			break;
		case 3:
			dailyOperations();
			break;
		case 4:
			supportedServices();
			break;
		case 5:
			allServers();
			break;
		case 6://Main menu
			return 1;
		case 7://logout and main menu
			logout();
			return 1;
		case 8:
			exit(1);
		default:
			noSuchOption();
			break;
		}
	}
}
int superUserOptionsServer(){
	int option;

	while( 1 ){


		fprintf(stdout, "\n\n\n1) Send a message \n");
		fprintf(stdout, "2) Update a service\n");
		fprintf(stdout, "3) Install a service\n");
		fprintf(stdout, "4) Uninstall a service\n");
		fprintf(stdout, "5) Create a User \n");
		fprintf(stdout, "6) Main menu \n");
		fprintf(stdout, "7) Logout \n");
		fprintf(stdout, "8) Exit\n\n" );
		option = getOption();
		switch( option ){
		case 1:
			sendMessage();
			break;
		case 2:
			updateService();
			break;
		case 3:
			installService();
			break;
		case 4:
			uninstallService();
			break;
		case 5:
			createUser();
			break;
		case 6://main menu
			return 1;
		case 7://logout and main menu
			logout();
			return 1;
		case 8:
			exit(1);
		default:
			noSuchOption();
			break;
		}
	}
}
int superUserOptionsFarm(){
	int option;

	while( 1 ){


		fprintf(stdout, "\n\n\n1) Change a Update server \n");
		fprintf(stdout, "2) Add a server\n");
		fprintf(stdout, "3) Add a supported service \n");
		fprintf(stdout, "4) Main menu \n");
		fprintf(stdout, "5) Logout\n");
		fprintf(stdout, "6) Exit\n\n");
		option = getOption();
		switch( option ){
		case 1: 
			changeUpdateServer();
			break;
		case 2:
			addServer();
			break;
		case 3:
			addSupportedService();
			break;
		case 4://main menu
			return 1;
		case 5://logout and main menu
			logout();
			return 1;
		case 6:
			exit(1);
		default:
			noSuchOption();
			break;
		}
	}
}
void mainMenu(){

	while( loggedType == 0 )
	{
		if( loginScreen() )
			printGreen("Logged in successfully\n");	
		else
		{
			printError("Critical login error.\n");
			exit(1);
		}
		switch(loggedType){
		case 1:
			userMainMenu();
			break;
		case 2:
			printMessages(loggedServerID);
			deleteMessages(loggedServerID);
			adminMainMenu();
			break;
		case 3:
			superUserMainMenu();
			break;
		default:
			printError("Incorrect user type.\n");
			inputToContinue();
			exit(1);
		}
	}
}

#endif
